﻿using System.Collections.Generic;
using System.Linq;
using System.Diagnostics.Contracts;

namespace IMModel.Domain.Common
{
    /// <summary>
    /// 
    /// </summary>
    public static class ItemExtensions
    {
        /// <summary>
        /// Получает суммарный вес подпунктов
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static double GetСhildrenWeight(this IItem source)
        {
            Contract.Requires(source != null);
            Contract.Requires(source.Items != null);
            return source.Items.Sum(x => x.Weight);
        }

        /// <summary>
        /// Получает нормализованный вес пункта
        /// </summary>
        /// <param name="source">Пункт индексной системы</param>
        /// <returns>Нормализованный вес пункта</returns>
        public static double GetNormalizedWeight(this IItem source)
        {
            Contract.Requires(source != null);
            Contract.Requires(source.Parent != null);
            Contract.Requires(source.Parent.GetСhildrenWeight() > 0);
            Contract.Ensures(Contract.Result<double>() >= 0);
            return source.Weight / source.Parent.GetСhildrenWeight();
        }

        /// <summary>
        /// Получает нормализованный вес пункта индексной системы с учётом весов всех его родительских пунктов
        /// </summary>
        /// <param name="source">Пункт индексной системы</param>
        /// <returns>Нормализованный вес пункта с учётом всех родительских пунктов</returns>
        public static double GetIndexedWeight(this IItem source)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result<double>() >= 0);
            IItem curr = source;
            double result = curr.Weight;
            while (curr.Parent != null)
            {
                result *= curr.GetNormalizedWeight();
                curr = curr.Parent;
            }
            return result;
        }

        /// <summary>
        /// Получает сумму нормализованых весов коллекции пунктов индексной системы
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static double SumIndexedWeight(this IEnumerable<IItem> source)
        {
            Contract.Requires(source != null);
            Contract.Requires(source.Count() > 0);
            Contract.Ensures(Contract.Result<double>() >= 0);
            return source.Sum(x => x.GetIndexedWeight());
        }
    }
}